//
//  ArrayUtils.swift
//  novelReader
//
//  Created by Ink on 2020/8/1.
//  Copyright © 2020 ChineseAll. All rights reserved.
//

extension Array {
    
    public subscript(safe index: Int?) -> Element? {
        get {
            guard let index = index, indices ~= index else { return nil }
            return self[index]
        }
        set {
            guard let index = index, indices ~= index else { return }
            if let newValue = newValue {
                self[index] = newValue
            } else {
                remove(at: index)
            }
        }
    }
}

extension Array {
    
    public func merge(_ element: Element?) -> [Element] {
        if let element = element {
            return self + [element]
        }
        return self
    }
    
    public func merge(_ elements: [Element]?) -> [Element] {
        if let elements = elements {
            return self + elements
        }
        return self
    }
    
    @inlinable public mutating func append(safe newElement: Element?) {
        guard let newElement = newElement else { return }
        append(newElement)
    }
    
    public func changeArray(_ step:Int,pageCount:Int) -> [Element] {
        
        var startIdx = step * pageCount
        var endIdx   = startIdx + pageCount - 1
        if endIdx >= self.count {
            startIdx = 0
            endIdx   = pageCount - 1
        }
        let data = Array(self[startIdx...endIdx])
        return data
    }
}

public enum OffsetDirection {
    case before
    case current
    case after
    case custom(Int)

    public var value: Int {
        switch self {
        case .before: return -1
        case .current: return 0
        case .after: return 1
        case .custom(let value): return value
        }
    }
}

public extension Array where Element: Equatable {
    
    @discardableResult
    mutating func remove(_ element: Element?) -> Element? {
        if let index = firstIndex(ofOptional: element) {
            return remove(at: index)
        }
        return nil
    }
    
    func firstIndex(ofOptional element: Element?) -> Int? {
        guard let element = element else {
            return nil
        }
        return firstIndex(of: element)
    }
    
    func element(_ element: Element?, direction:OffsetDirection = .current) -> Element? {
        guard let index = firstIndex(ofOptional: element) else {
            return nil
        }
        
        return self[safe: index + direction.value]
    }
}
